跳到主要内容

Unity 的执行流程

参考资料

Unity 官方文档 Script API

Unity 生命周期

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// Unity脚本执行顺序 测试
/// </summary>
public class TestCallSequence : MonoBehaviour
{

void Awake() {
Debug.Log("Awake^^^^^^^^^^^^^");
}

void OnEnable() {
Debug.Log("OnEnable^^^^^^^^^^^^^");
}
// Use this for initialization
void Start() {
Debug.Log("Start^^^^^^^^^^^^^");
}

void FixedUpdate() {
Debug.Log("FixedUpdate^^^^^^^^^^^^^");

}
// Update is called once per frame
void Update() {
Debug.Log("Update^^^^^^^^^^^^^");

}

void LateUpdate() {
Debug.Log("LateUpdate^^^^^^^^^^^^^");

}

void OnGUI() {
Debug.Log("OnGUI^^^^^^^^^^^^^");
}

void Reset() {
Debug.Log("Reset^^^^^^^^^^^^^");
}

void OnDisable() {
Debug.Log("OnDisable^^^^^^^^^^^^^");
}

void OnDestroy() {
Debug.Log("OnDestroy^^^^^^^^^^^^^");
}
}

不同脚本之间的执行顺序

参考资料 浅谈Unity的脚本执行顺序

Unity 中某个脚本的执行顺序是 Awake、Start、Update、LateUpdate 等,但是不同的脚本之间的执行顺序是怎样的呢?

Unity 后台是单线程执行的,所谓的协程都是伪多线程。不同脚本的 Awake 在后台的执行真相是这样的:

后台Awake()  
{
脚本0Awake();
脚本1Awake();
........
}

Unity 提供了一个设置不同脚本之间执行顺序的功能,在 Unity 里面可以点击 edit->project settings->Script Execution Order 中自定义脚本执行顺序,order值越小的越先执行,order值越大的越后执行

image.png

Update 和 FixedUpdate

void Update() 更新  void FixedUpdate() 固定更新

Update 跟当前平台的帧数有关,而 FixedUpdate 是真实时间,所以处理物理逻辑的时候要把代码放在 FixedUpdate 而不是 Update。

Update 是在每次渲染新的一帧的时候才会调用,也就是说,这个函数的更新频率和设备的性能有关以及被渲染的物体(可以认为是三角形的数量)。在性能好的机器上可能 fps 30,差的可能小些。这会导致同一个游戏在不同的机器上效果不一致,有的快有的慢。因为 Update 的执行间隔不一样了。

而 FixedUpdate,是在固定的时间间隔执行,不受游戏帧率的影响。所以处理 Rigidbody 的时候最好用 FixedUpdate。

LateUpdate

LateUpdate 是在所有 Update 函数调用后被调用。这可用于调整脚本执行顺序。例如:当物体在 Update 里移动时,跟随物体的相机可以在 LateUpdate 里实现。

DontDestroyOnLoad

让该实例切换场景时不被销毁

DontDestroyOnLoad(singleton);

Awake 和 Start 的区别

相同点:

  • 两者都是对象初始化时调用的,都在 Update 之前,场景中的对象都生成后才会调用 Awake,Awake 调用完才会调用 Start,所有Start 调用完才会开始 Update。
  • 两者在对象生命周期内都只会被调用一次,即初始化时被调用,之后即使是在被重新激活之后也不会再次被调用。

不同点:

  • Awake 函数在对象初始化之后立刻就会调用,换句话说,对象初始化之后第一调用的函数就是 Awake;而 Start 是在对象初始化后,第一次 Update 之前调用的,在 Start 中进行初始化不是很安全,因为它可能被其他自定义的函数抢先。
  • Awake 不管对象是否是 Active,脚本是否 enabled 都会被调用,可以说是无论如何都会被调用的;而 Start 如果对象被 SetAcive(false) 或者 enabled= false 了是不会被调用的。

脚本的一些成员,如果想在创建之后的代码中立即使用,则必须写在 Awake() 里面;(总之和 new 相关的就放在 Awake)

当关卡加载时,脚本的 Awake 的次序是不能控制的;

而开启协程不能在 Awake 中进行,得在 Start 里面开启